import java.rmi.RemoteException;
import java.util.Vector;
public class ServerObject implements ServerObject_itf {

	/**
	 * 
	 */
	private static final long serialVersionUID = 2437733159136174245L;

	/**
	 * that's what the server manipulates as SharedObject
	 */

	private enum ServerObjectLock {
		NL, //No Lock
		RL, //Read Lock
		WL  //Write Lock
	}
	
	private int id;
	private Object obj;
	private Client_itf writer;
	private Vector<Client_itf> readers; // readers'list
	private ServerObjectLock lock;

	
	public ServerObject(int id, Object obj){
		this.id = id;
		this.obj = obj;
		this.lock = ServerObjectLock.NL;
		this.readers = new Vector<Client_itf>();
		this.writer = null;
		
	}
	
	@Override    
	public synchronized Object lock_read(Client_itf client) {
		
		if(lock == ServerObjectLock.WL)
		{
			try {
				this.obj = writer.reduce_lock(this.id);
			} catch (RemoteException e) {
				e.printStackTrace();
			}
			readers.add(writer);
			
		}

		writer = null;
		this.lock=ServerObjectLock.RL;
		this.readers.add(client);
		
		return obj;
	}

	@Override
	public synchronized Object lock_write(Client_itf client) {
		
		if(lock == ServerObjectLock.RL)
		{
			readers.remove(client);

			for (Client_itf c : readers) {
					try {
						c.invalidate_reader(this.id);
					} catch (RemoteException e) {
						e.printStackTrace();
					}
			}
		}
		else if(lock == ServerObjectLock.WL)
		{
				try {
					this.obj = this.writer.invalidate_writer(this.id);
				} catch (RemoteException e) {
					e.printStackTrace();
				}
		}

		readers.clear(); 
		writer = client;
		lock = ServerObjectLock.WL; 

		return obj; 

	}


	public synchronized Object getObject() {
		
		return this.obj;
	}

}
